#include "e2d/core/render/SkinnedMeshRender.h"
#include "e2d/core/trans/TransformNode.h"
#include "e2d/core/Entity.h"
#include "e2d/core/EntityMap.h"
#include "e2d/core/trans/TransformNode.h"


void e2d::SkinnedMeshRender::InitRootNodeIfNull()
{
	if (m_RootNode.m_UUID.empty()) {
		m_RootNode = e2d::EntityMap(m_Entity->m_Parent);
	}
}

void e2d::SkinnedMeshRender::OnLoad()
{
	// if rootNode is null
	InitRootNodeIfNull();

	m_RootNode.LoadFromScene(m_Entity->m_Scene);
	m_MeshMap.OnLoad();
	m_BoneFileMap.OnLoad();
	m_MaterialView.OnLoad();

	if (m_BoneFileMap.m_Value)
		SetBoneEntities();
}

void e2d::SkinnedMeshRender::OnStart()
{
}


void e2d::SkinnedMeshRender::OnUpdate()
{

}

void e2d::SkinnedMeshRender::OnUpdateRuntime()
{
	if (!m_RootNode.m_Entity)
	{
		//ztclog::info("null root node");
		return;
	}

	auto m_Bones = m_BoneFileMap.m_Value;

	if (!m_Bones)
	{
		ztclog::info("null bones map filed ");
		return;
	}

	const auto& rootTransform = m_RootNode.m_Entity->GetOrEmplace<e2d::TransformNode>();
	glm::mat4 rootBoneWorldInv = glm::inverse(rootTransform.m_World.GetWorld());

	for (const auto& it : m_Bones->m_Bones)
	{
		const auto& bone = it.second;

		auto entity = bone.m_Entity;
	
		if (!entity)
			continue;
		
		auto& worldTransform = entity->GetWorldTransform();
		m_BoneData.bones[bone.m_Index] = rootBoneWorldInv * worldTransform.GetWorld() * bone.m_OffsetMatrix.GetWorld();
	}
}

void e2d::SkinnedMeshRender::OnDestroy()
{
}

void e2d::SkinnedMeshRender::SetBoneEntities()
{
	ProcessEntityNode(m_RootNode.m_Entity);
}

bool e2d::SkinnedMeshRender::ProcessEntityNode(e2d::Entity* entity)
{
	if (!entity)
	{
		return false;
	}
	auto m_Bones = m_BoneFileMap.m_Value;

	if (!m_Bones)
	{
		ztclog::info("null boneMap");
		return false;
	}
	auto& bones =  m_Bones->m_Bones;

	auto boneIt = bones.find(entity->m_Name);

	if (boneIt != bones.end())
	{
		auto& bone = boneIt->second;
		bone.m_Entity = entity;
	};

	for (auto child : entity->m_Children) {
		ProcessEntityNode(child.get());
	}
	return true;
}

std::shared_ptr<fxcc::graph::common::MeshJack> e2d::SkinnedMeshRender::GetMesh() const
{
	return m_MeshMap.m_Value;
}

